# -*- coding: utf-8 -*-
# created on 2016/5/12


from sympy import log, Mul
from mathsolver.functions.base import *
from mathsolver.functions.sympy_utils import default_symbol
from mathsolver.functions.sympy_utils import get_all_child


# 代数式有意义问题
class ShuYuShiFenShi001(BaseFunction):
    def solver(self, *args):
        """
        代数式有意义
        :param args:
        :return:
        """
        expr = args[0].sympify()
        assert len(expr.free_symbols) > 0, "need one free symbol"
        target = default_symbol(expr)

        parts1 = get_all_child(expr, lambda xx: xx.is_Pow and xx.has(target) and xx.args[1].is_Number)
        parts2 = get_all_child(expr, lambda xx: isinstance(xx, log) and xx.has(target))

        ineqs = []
        for part in parts1:
            if 0 < part.args[1] < 1 and (1 / part.args[1]).is_even:
                ineqs.append((part.args[0], ">=", S.Zero))
            elif part.args[1] < 0 and part.args[1].is_even or (1 / part.args[1]).is_even:
                ineqs.append((part.args[0], ">", S.Zero))
            elif part.args[1] <= 0:
                ineqs.append((part.args[0], "!=", S.Zero))

        for part in parts2:
            ineqs.append((part.args[0], ">", S.Zero))

        if ineqs:
            self.steps.append(["依题意，得：", ",".join([self.output_eq(ineq) for ineq in ineqs])])

        if len(ineqs) == 1:
            self.output.append(BaseIneq(ineqs[0]))
            self.label.add("代数式有意义问题")
        elif len(ineqs) > 1:
            self.output.append(BaseIneqs(ineqs))
            self.label.add("代数式有意义问题")
        else:
            self.output.append(BaseSymbolValue({target: S.Reals}))
        return self


class FangChenFenShiGongFenMu(BaseFunction):
    @staticmethod
    def get_gongfenmu_two_fenshi(f1, f2):
        eq = (f1 - f2).together().cancel()  # 将f1和f2通分并化简
        return eq

    def get_steps(self, fs):
        for f in fs:
            self.steps.append(["", "分式%s的分母是: %s" % (new_latex(f), new_latex(f.args[0]))])

    def solver(self, *args):
        """
        求代数式的最简公分母
        :param args:
        :return:
        """
        fs = args[0].sympify()
        assert len(fs) >= 2
        # 排除分式中分子部分的常数因子
        if not fs[0].is_Pow:
            for i in range(len(fs)):
                for item in fs[i].args:
                    if item.is_Pow:
                        fs[i] = item
        # 给前两个分式通分并化简
        eq = self.get_gongfenmu_two_fenshi(fs[0], fs[1])
        # 如果分式的数量多于3个，将之前通分的结果作为新的分式与后面的分式进一步通分并化简
        if len(fs) > 2:
            for i in range(2, len(fs)):
                eq = self.get_gongfenmu_two_fenshi(eq, fs[i])
        self.get_steps(fs)
        # 获取通分后分式的分母
        if eq.is_Mul:
            denominators = [1 / arg for arg in eq.args if
                            not arg.is_Integer and arg.is_Number or arg.is_Pow and arg.args[1] == -1]
            gongfenmu = Mul._from_args(denominators).factor()
        elif eq.is_Pow:
            gongfenmu = eq.args[0]
        else:
            raise ValueError("unexpected situation")
        # 将分母合并同类项
        self.steps.append(["依题意，", "最后的最简公分母是: %s" % new_latex(gongfenmu)])
        self.output.append(BasePoly(gongfenmu))
        return self


def judgement_parts(xx):
    if len(xx.free_symbols) > 0:
        if xx.is_Pow:
            if xx.args[1] < 0:
                return True
            elif xx.args[1] == 0:
                return True
            else:
                q = xx.args[1].q
                if (q % 2) == 0:
                    return True
    else:
        return False


def get_parts(expr):
    childrens = []
    if judgement_parts(expr):
        return [expr]
    if hasattr(expr, "args"):
        for arg in expr.args:
            if judgement_parts(arg):
                childrens.append(arg)
            else:
                childrens.extend(get_parts(arg))
        return childrens
    else:

        return childrens


# 代数式有意义
class ShuyuShiFenShi002(BaseFunction):
    def solver(self, *args):
        expr = args[0].sympify()
        assert len(expr.free_symbols) > 0, "need one free symbol"
        parts = get_parts(expr)
        assert len(parts) > 0

        ineqs = []
        for part in parts:
            if part.args[1] > 0 and part.args[1].is_even or (1 / part.args[1]).is_even:
                ineqs.append((part.args[0], ">=", S.Zero))
            elif part.args[1] < 0 and part.args[1].is_even or (1 / part.args[1]).is_even:
                if part.args[1] == -1 or part.args[1] == 0:
                    ineqs.append((part.args[0], "\\neq", S.Zero))
                elif (part.args[1].q % 2) == 0:
                    ineqs.append((part.args[0], ">", S.Zero))
                elif part.args[1] <= 0:
                    ineqs.append((part.args[0], "!=", S.Zero))
        return self


if __name__ == '__main__':
    pass
